﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;

using System.Linq;
using System.Xml.Linq;

using ProjectBase.Core;
using ProjectBase.Data;
using ProjectBase.Data.Xml;

using $prjsn$.Entity.Services.HowTos;
using $prjsn$.Common;
using $prjsn$.Common.Data.Services.HowTos;

namespace $safeprojectname$.Services.HowTos.Xml
{
    [CLSCompliant(false)]
    public class ComplexEntityDao : BaseXmlDao<ComplexEntity, long, ComplexEntityFilter>, IComplexEntityDao
    {
        protected const string Verylongname = "VeryLongName";
        protected const string Image = "Image";

        #region Find
        /// <summary>
        /// Fills the Criteria list with where statements based on provided filter
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public override IEnumerable<ComplexEntity> Find(ComplexEntityFilter filter)
        {
            // Equal
            Criteria.Add(entity => entity.ID.IsEqual(filter.IdExact));
            Criteria.Add(entity => entity.Code.IsExact(filter.CodeExact)); // exact match even for string.Empty

            // Like
            Criteria.Add(entity => entity.Code.IsLike(filter.Code));
            Criteria.Add(entity => entity.ShortName.IsLike(filter.ShortName));
            Criteria.Add(entity => entity.VeryLongName.IsLike(filter.VeryLongName));

            Criteria.Add(entity => entity.IsApproved.IsEqual(filter.IsApproved));
            Criteria.Add(entity => entity.IsSigned.IsEqual(filter.IsSigned));

            #region SimpleEntity
            Criteria.Add(entity => entity.SimpleCombo
                .IsEqual<SimpleEntity, string>(filter.SimpleCombo));
            Criteria.Add(entity => entity.SimpleAsync
                .IsEqual<SimpleEntity, string>(filter.SimpleAsync));
            Criteria.Add(entity => entity.SimpleAuto
                .IsEqual<SimpleEntity, string>(filter.SimpleAuto));
            #endregion SimpleEntity

            #region Byte
            Criteria.Add(entity => entity.ByteValue.Compare(filter.ByteValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ByteValue.Compare(filter.ByteValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.ByteValueNullable.Compare(filter.ByteValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ByteValueNullable.Compare(filter.ByteValueNullableTo, Sign.LessOrEqual));

            Criteria.Add(entity => entity.SByteValue.Compare(filter.SByteValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.SByteValue.Compare(filter.SByteValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.SByteValueNullable.Compare(filter.SByteValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.SByteValueNullable.Compare(filter.SByteValueNullableTo, Sign.LessOrEqual));
            #endregion Byte

            #region Short
            Criteria.Add(entity => entity.ShortValue.Compare(filter.ShortValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ShortValue.Compare(filter.ShortValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.ShortValueNullable.Compare(filter.ShortValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ShortValueNullable.Compare(filter.ShortValueNullableTo, Sign.LessOrEqual));

            Criteria.Add(entity => entity.UShortValue.Compare(filter.UShortValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.UShortValue.Compare(filter.UShortValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.UShortValueNullable.Compare(filter.UShortValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.UShortValueNullable.Compare(filter.UShortValueNullableTo, Sign.LessOrEqual));
            #endregion Short

            #region Int
            Criteria.Add(entity => entity.IntValue.Compare(filter.IntValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.IntValue.Compare(filter.IntValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.IntValueNullable.Compare(filter.IntValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.IntValueNullable.Compare(filter.IntValueNullableTo, Sign.LessOrEqual));

            Criteria.Add(entity => entity.UIntValue.Compare(filter.UIntValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.UIntValue.Compare(filter.UIntValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.UIntValueNullable.Compare(filter.UIntValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.UIntValueNullable.Compare(filter.UIntValueNullableTo, Sign.LessOrEqual));
            #endregion Int

            #region Long
            Criteria.Add(entity => entity.LongValue.Compare(filter.LongValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.LongValue.Compare(filter.LongValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.LongValueNullable.Compare(filter.LongValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.LongValueNullable.Compare(filter.LongValueNullableTo, Sign.LessOrEqual));

            Criteria.Add(entity => entity.ULongValue.Compare(filter.ULongValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ULongValue.Compare(filter.ULongValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.ULongValueNullable.Compare(filter.ULongValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ULongValueNullable.Compare(filter.ULongValueNullableTo, Sign.LessOrEqual));
            #endregion Long

            #region Decimal
            Criteria.Add(entity => entity.DecimalValue.Compare(filter.DecimalValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.DecimalValue.Compare(filter.DecimalValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.DecimalValueNullable.Compare(filter.DecimalValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.DecimalValueNullable.Compare(filter.DecimalValueNullableTo, Sign.LessOrEqual));
            #endregion Decimal

            #region Double
            Criteria.Add(entity => entity.DoubleValue.Compare(filter.DoubleValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.DoubleValue.Compare(filter.DoubleValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.DoubleValueNullable.Compare(filter.DoubleValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.DoubleValueNullable.Compare(filter.DoubleValueNullableTo, Sign.LessOrEqual));
            #endregion Double

            #region Float
            Criteria.Add(entity => entity.FloatValue.Compare(filter.FloatValueFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.FloatValue.Compare(filter.FloatValueTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.FloatValueNullable.Compare(filter.FloatValueNullableFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.FloatValueNullable.Compare(filter.FloatValueNullableTo, Sign.LessOrEqual));
            #endregion Float

            #region Valid
            Criteria.Add(entity => entity.ValidFrom.Compare(filter.ValidFromFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ValidFrom.Compare(filter.ValidFromTo, Sign.LessOrEqual));
            Criteria.Add(entity => entity.ValidTo.Compare(filter.ValidToFrom, Sign.GreaterOrEqual));
            Criteria.Add(entity => entity.ValidTo.Compare(filter.ValidToTo, Sign.LessOrEqual));
            #endregion Valid


            return GetListByCriteria(filter);
        }
        #endregion Find

        #region XML - ENTITY mapping
        /// <summary>
        /// Converts the XElement into the ComplexEntity
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        protected override ComplexEntity CreateEntity(XElement element)
        {
            var entity = FillEntity(new ComplexEntity(), element); // base converts ValueTypes and String

            if (element.Elements(Verylongname).Any())
            {
                entity.VeryLongName = element.Elements(Verylongname).First().Value;
            }
            if (element.Elements(Image).Any())
            {
                var text = element.Elements(Image).First().Value;
                entity.Image = Convert.FromBase64String(text);
            }

            entity.SimpleCombo = SimpleEntityDao.GetById((string)element.Attribute("SimpleComboId"));
            entity.SimpleAsync = SimpleEntityDao.GetById((string)element.Attribute("SimpleAsyncId"));
            entity.SimpleAuto = SimpleEntityDao.GetById((string)element.Attribute("SimpleAutoId"));

            entity.SetId((long)element.Attribute(Str.Common.ID));
            return entity;
        }
        /// <summary>
        /// Converts the ComplexEntity instnace into the XElement
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected override XElement CreateElement(ComplexEntity entity)
        {
            var element = base.CreateElement(entity); // base converts ValueTypes and String

            // VeryLongName
            if (element.Attribute(Verylongname).Is())
            {
                element.Attribute(Verylongname).Remove();
            }

            element.Add(new XElement(Verylongname) { Value = entity.VeryLongName });

            // Image
            if (element.Attribute(Image).Is())
            {
                element.Attribute(Image).Remove();
            }
            if (entity.Image.Is())
            {
                var text = Convert.ToBase64String(entity.Image, 0, entity.Image.Length);
                element.Add(new XElement(Image) { Value = text });
            }

            element.Add(new XAttribute("SimpleComboId", entity.SimpleCombo.ID));
            element.Add(new XAttribute("SimpleAsyncId", entity.SimpleAsync.ID));
            if (entity.SimpleAuto.Is())
            {
                element.Add(new XAttribute("SimpleAutoId", entity.SimpleAuto.ID));
            }

            return element;
        }
        /// <summary>
        ///     Incremented 'Next ID' generator.
        ///     Searches for the max existing used value
        ///     and returnes that + 1
        /// </summary>
        /// <returns></returns>
        protected override long GetNextId(ComplexEntity entity = null)
        {
            long id = 0; // in case there is no element yet
            if (TheList.Count() > 0) // element(s) exist(s) - find the largest ID
            {
                id = TheList.Max<ComplexEntity, long>(e => e.ID);
            }
            return ++id;
        }
        #endregion XML - ENTITY mapping

        #region properties IoC
        // see interface IComplexEntityDao declaration:
        //   ISimpleEntityDao SimpleEntityDao { set; }
        // that will allow injecting! below declaration is not enough for default factory
        public virtual ISimpleEntityDao SimpleEntityDao { protected get; set; }
        #endregion properties IoC
    }
}

